﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Common;
using log4net;
using AutoFacUtils;
using CashFlow.ShopManage.Def;
using CashFlow.Db.DAL;
using CashFlow.Db.Entity;
using CashFlow.Db.Repository;
using CashFlow.ShopManage.Service;
using CashFlow.ShopManage.Common;

namespace CashFlow.ShopManage.Service.Implement
{
    public class UserService : Service<UserInfoEntity>, IUserService
    {
        private static ILog _logger = LogManager.GetLogger(typeof(UserService));
        private IAdminService GetAdminService() { return AutoFacHelper.Get<IAdminService>(); }
        private IUserService GetUserService() { return AutoFacHelper.Get<IUserService>(); }
        private IShopService GetShopService() { return AutoFacHelper.Get<IShopService>(); }
        private IShopUserService GetShopUserService() { return AutoFacHelper.Get<IShopUserService>(); }

        public IList<UserInfoEntity> QueryShopAllUsersByShopManagerUserId(
            int shopManagerUserId
            , int? state)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var query = db.Queryable<UserInfoEntity>()
                              .InnerJoin<ShopUserEntity>((u, su) => u.Id == su.UserId)
                              .Where((u, su) => su.ShopManagerUserId == shopManagerUserId);

                if (state.HasValue)
                {
                    query = query.Where((u, su) => u.State == state);
                }

                var ls = query.Select((u, su) => u).ToList();
                return ls;
            }
        }

        public IList<int> QueryShopAllUsersIdByShopManagerUserId(
            int shopManagerUserId
            , int? state)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var query = db.Queryable<UserInfoEntity>()
                              .InnerJoin<ShopUserEntity>((u, su) => u.Id == su.UserId)
                              .Where((u, su) => su.ShopManagerUserId == shopManagerUserId);

                if (state.HasValue)
                {
                    query = query.Where((u, su) => u.State == state);
                }

                var ls = query.Select((u, su) => u.Id).ToList();
                return ls;
            }
        }

        public IList<UserInfoAndReferenceUserInfo> QueryShopAllUsersByShopManagerUserId2(
            int shopManagerUserId
            , int? state)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var query = db.Queryable<UserInfoEntity>()
                              .InnerJoin<ShopUserEntity>((u, su) => u.Id == su.UserId)
                              .InnerJoin<UserInfoEntity>((u, su, u2) => u.ReferenceInvitationCode == u2.InvitationCode)
                              .Where((u, su, u2) => su.ShopManagerUserId == shopManagerUserId);

                if (state.HasValue)
                {
                    query = query.Where((u, su, u2) => u.State == state);
                }

                var ls = query.Select((u, su, u2) => new UserInfoAndReferenceUserInfo
                {
                    UserInfo = u,
                    ReferenceUserInfo = u2
                }).ToList();

                return ls;
            }
        }

        public IList<UserInfoEntity> QueryShopAllUsersByUserId(
            int userId
            , int? state)
        {
            var ls = new List<UserInfoEntity>();

            var service = GetAdminService();
            var ui = service.GetLoginUserInfo();
            var lsShopUsers = QueryShopAllUsersByShopManagerUserId(
                                ui.ShopManagerUserId
                                , state
                              );
            var self = lsShopUsers.Where(x => x.Id == userId).FirstOrDefault();
            if (self != null && self.Id > 0)
            {
                Queue<string> queue = new Queue<string>();
                queue.Enqueue(self.InvitationCode);
                ls.Add(self);
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    var ls2 = lsShopUsers.Where(x => x.ReferenceInvitationCode == item).ToList();
                    foreach (var item2 in ls2)
                    {
                        queue.Enqueue(item2.InvitationCode);
                        ls.Add(item2);
                    }
                }
            }

            if (state.HasValue)
            {
                ls = ls.Where(x => x.State == state.Value).ToList();
            }

            return ls;
        }

        private UserInfoAndReferenceUserInfo UserInfo_2_UserInfoAndReferenceUserInfo(
            UserInfoEntity entity
            , IList<UserInfoEntity> users)
        {
            var item = users.Where(x => x.InvitationCode == entity.ReferenceInvitationCode)
                            .FirstOrDefault();
            return new UserInfoAndReferenceUserInfo
            {
                UserInfo = entity,
                ReferenceUserInfo = item
            };
        }

        public IList<UserInfoAndReferenceUserInfo> QueryShopAllUsersByShopManagerUserIdByWhere(
            int shopManagerUserId
            , string phone
            , string name
            , string invitationCode
            , string reference
            , string referenceInvitationCode
            , int? state)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var query = db.Queryable<UserInfoEntity>()
                              .InnerJoin<ShopUserEntity>((u, su) => u.Id == su.UserId)
                              .InnerJoin<UserInfoEntity>((u, su, u2) => u.ReferenceInvitationCode == u2.InvitationCode)
                              .Where((u, su, u2) => su.ShopManagerUserId == shopManagerUserId);

                if (!string.IsNullOrEmpty(phone))
                {
                    query = query.Where((u, su, u2) => u.Phone.Contains(phone));
                }
                if (!string.IsNullOrEmpty(name))
                {
                    query = query.Where((u, su, u2) => u.Name.Contains(name));
                }
                if (!string.IsNullOrEmpty(invitationCode))
                {
                    query = query.Where((u, su, u2) => u.InvitationCode.Contains(invitationCode));
                }
                if (!string.IsNullOrEmpty(reference))
                {
                    query = query.Where((u, su, u2) => u2.Name.Contains(reference));
                }
                if (!string.IsNullOrEmpty(referenceInvitationCode))
                {
                    query = query.Where((u, su, u2) => u.ReferenceInvitationCode.Contains(referenceInvitationCode));
                }
                if (state.HasValue)
                {
                    query = query.Where((u, su, u2) => u.State == state);
                }

                var ls = query.Select((u, su, u2) => new UserInfoAndReferenceUserInfo
                {
                    UserInfo = u,
                    ReferenceUserInfo = u2
                }).ToList();

                return ls;
            }
        }

        public UserInfoEntity QueryByInvitationCode(int shopManagerUserId
            , string invitationCode)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = db.Queryable<ShopUserEntity>()
                               .InnerJoin<UserInfoEntity>((su, u) => su.UserId == u.Id)
                               .Where((su, u) => su.ShopManagerUserId == shopManagerUserId
                                    && u.InvitationCode == invitationCode)
                               .Select((su, u) => u)
                               .First();
                return entity;
            }
        }

        public EUpdateUserResult UpdateUser(int userId
            , string phone
            , string name)
        {
            EUpdateUserResult result = EUpdateUserResult.Other;

            using (var db = SqlSugarHelper.GetDb())
            {
                int n = db.Queryable<UserInfoEntity>()
                          .Where(x => x.Phone == phone && x.Id != userId)
                          .Count();
                if (n > 0)
                {
                    result = EUpdateUserResult.ExistPhone;
                }
                else
                {
                    var entity = new UserInfoEntity
                    {
                        Id = userId
                    };
                    db.Tracking(entity);
                    entity.Phone = phone;
                    entity.Name = name;
                    int n2 = db.Updateable<UserInfoEntity>(entity).ExecuteCommand();
                    if (n2 > 0)
                    {
                        result = EUpdateUserResult.Success;
                    }
                }
            }

            if (result != EUpdateUserResult.Success)
            {
                string text = string.Format("Update User Fail, result: {0}, userId = {1}, phone = {2}, name = {3}"
                    , (int)result
                    , userId
                    , phone
                    , name);
                _logger.Error(text);
            }

            return result;
        }

        public bool ResetPwd(int userId, string newPwd)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = new UserInfoEntity();
                entity.Password = newPwd;
                int n = db.Updateable(entity)
                          .UpdateColumns(x => x.Password)
                          .Where(x => x.Id == userId)
                          .ExecuteCommand();
                return n > 0;
            }
        }

        public bool UpdateShopManagerLevelPercent(int userId, decimal percent)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = new UserInfoEntity();
                entity.ShopManagerLevelPercent = percent;
                int n = db.Updateable(entity)
                          .UpdateColumns(c => c.ShopManagerLevelPercent)
                          .Where(x => x.Id == userId)
                          .ExecuteCommand();
                return n > 0;
            }
        }

        public bool UpdateUserState(int userId, int state)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = new UserInfoEntity();
                entity.State = state;
                int n = db.Updateable(entity)
                          .UpdateColumns(x => x.State)
                          .Where(x => x.Id == userId)
                          .ExecuteCommand();
                return n > 0;
            }
        }

        public bool UpdateUserReferenceInvitationCode(int userId
            , string invitationCode)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = new UserInfoEntity();
                entity.ReferenceInvitationCode = invitationCode;
                int n = db.Updateable(entity)
                          .UpdateColumns(x => x.ReferenceInvitationCode)
                          .Where(x => x.Id == userId)
                          .ExecuteCommand();
                return n > 0;
            }
        }
    }
}